//package com.lengxf.gateway.bak;
//
//import cn.hutool.core.bean.BeanUtil;
//import cn.hutool.json.JSONUtil;
//import com.lengxf.gateway.model.ProxyModel;
//import io.netty.buffer.ByteBufAllocator;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.logging.log4j.util.Strings;
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
//import org.springframework.cloud.gateway.filter.GlobalFilter;
//import org.springframework.core.Ordered;
//import org.springframework.core.io.ByteArrayResource;
//import org.springframework.core.io.buffer.DataBuffer;
//import org.springframework.core.io.buffer.DataBufferUtils;
//import org.springframework.core.io.buffer.NettyDataBufferFactory;
//import org.springframework.http.HttpHeaders;
//import org.springframework.http.HttpMethod;
//import org.springframework.http.MediaType;
//import org.springframework.http.server.reactive.ServerHttpRequest;
//import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
//import org.springframework.lang.NonNull;
//import org.springframework.stereotype.Component;
//import org.springframework.web.server.ServerWebExchange;
//import reactor.core.publisher.Flux;
//import reactor.core.publisher.Mono;
//
//import java.net.URI;
//import java.nio.charset.Charset;
//import java.nio.charset.StandardCharsets;
//import java.util.Arrays;
//import java.util.Map;
//import java.util.Objects;
//import java.util.concurrent.ConcurrentHashMap;
//import java.util.regex.Pattern;
//import java.util.stream.Collectors;
//
//import static com.lengxf.gateway.bak.BodyUtils.LOCAL_CACHED_REQUEST_BODY;
//
//
//
///**
// * 包装请求后转发到代理服务
// * @Author Lengxf
// */
//@Component
//public class CharacterEscapeGlobalFilter implements GlobalFilter, Ordered {
//
//    private final static String URI_HEADER = "resourceUrl";
//    private final static String PROXY_URI = "http://localhost:8889/auth/proxy";
//
//    private static final Pattern NULL_CHAR = Pattern.compile("\0");
//    private static final Pattern[] XSS_PATTERN;
//
//    static {
//        XSS_PATTERN = new Pattern[]{
//                Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE),
//                Pattern.compile("<a(.*?)</a>", Pattern.CASE_INSENSITIVE),
//                Pattern.compile("href(.*?)=", Pattern.CASE_INSENSITIVE),
//                Pattern.compile("src[\r\n]*=[\r\n]*'(.*?)'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
//                Pattern.compile("src[\r\n]*=[\r\n]*\"(.*?)\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
//                Pattern.compile("</script>", Pattern.CASE_INSENSITIVE),
//                Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
//                Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
//                Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
//                Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE),
//                Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE),
//                Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
//                Pattern.compile("<iframe>(.*?)</iframe>", Pattern.CASE_INSENSITIVE),
//                Pattern.compile("</iframe>", Pattern.CASE_INSENSITIVE),
//                Pattern.compile("<iframe(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
//        };
//    }
//
//    private static String buildProxyParams(ProxyModel proxyModel) {
//        return String.format("%s=%s", "params", JSONUtil.toJsonStr(proxyModel));
//    }
//
//    private static byte[] getMultiPartFormBody(ServerWebExchange exchange, DataBuffer body, Charset charset) {
//        return new byte[0];
//    }
//
//    private static byte[] getFormBody(ServerWebExchange exchange, DataBuffer body, Charset charset) {
//        byte[] bytes = new byte[body.readableByteCount()];
//        body.read(bytes);
//        String bodyString = new String(bytes, charset);
//        ServerHttpRequest request = exchange.getRequest();
//        HttpHeaders headers = request.getHeaders();
//        ProxyModel proxyModel = new ProxyModel().setPath(request.getURI().getPath())
//                .setMethod(HttpMethod.POST).setHeaders(headers);
//        if (StringUtils.isNotBlank(bodyString)) {
//            Map<String, Object> params = Arrays.stream(bodyString.split("&"))
//                    .map(e -> e.split("=")).collect(Collectors.toMap(e -> e[0], e -> e[1]));
//            proxyModel.setParams(params);
//        }
//        DataBufferUtils.release(body);
//        return buildProxyParams(proxyModel).getBytes(charset);
//    }
//
//    @Override
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        DataBuffer cachedRequestBody = exchange.getAttributeOrDefault(LOCAL_CACHED_REQUEST_BODY, null);
//        ServerHttpRequest decorator = escapeRequest(exchange, cachedRequestBody)
//                .mutate().method(HttpMethod.POST).build();
//        exchange.getAttributes().remove(LOCAL_CACHED_REQUEST_BODY);
//        return chain.filter(exchange.mutate().request(decorator).build());
//    }
//
//    @Override
//    public int getOrder() {
//        return Ordered.HIGHEST_PRECEDENCE + 20000;
//    }
//
//
//    private ServerHttpRequest escapeRequest(ServerWebExchange exchange, DataBuffer cachedRequestBody) {
//        ServerHttpRequest request = exchange.getRequest();
//        final HttpHeaders newHeaders = new HttpHeaders();
//        HttpHeaders originalHeaders = request.getHeaders();
//        for (String key : originalHeaders.keySet()) {
//            String encodeKey = xssEncode(key);
//            String value = originalHeaders.getFirst(encodeKey);
//            if (value != null) {
//                newHeaders.set(encodeKey, xssEncode(value));
//            } else {
//                newHeaders.set(encodeKey, null);
//            }
//        }
//        MediaType contentType = newHeaders.getContentType();
//        Charset charset = getCharset(contentType);
//        String method = request.getMethodValue();
//        if (HttpMethod.GET.matches(method)) {
//            return doGetDecorate(request, newHeaders, charset);
//        }
//        if (Objects.isNull(cachedRequestBody)) {
//            return decorate(request, newHeaders, null);
//        }
//        byte[] newBody = getNewBody(exchange, cachedRequestBody, charset, getSwitchContentType(contentType));
//        newHeaders.setContentLength(newBody.length);
//        return decorate(request, newHeaders, newBody);
//    }
//
//    private ServerHttpRequestDecorator doGetDecorate(ServerHttpRequest request, HttpHeaders headers, Charset charset) {
//        Map<String, String> stringStringMap = request.getQueryParams().toSingleValueMap();
//        Map<String, Object> map = new ConcurrentHashMap<>();
//        BeanUtil.copyProperties(stringStringMap, map);
//        ProxyModel proxyModel = new ProxyModel().setPath(request.getURI().getPath())
//                .setMethod(HttpMethod.GET).setHeaders(headers).setParams(map);
//        return decorate(request, headers, buildProxyParams(proxyModel).getBytes(charset));
//    }
//
//    private Charset getCharset(MediaType contentType) {
//        return Objects.isNull(contentType) ? StandardCharsets.UTF_8
//                : (Objects.isNull(contentType.getCharset())) ? StandardCharsets.UTF_8
//                : contentType.getCharset();
//    }
//
//    private String getSwitchContentType(MediaType contentType) {
//        if (contentType == null) {
//            return "";
//        }
//        if (contentType.toString().contains(";")) {
//            return contentType.toString().substring(0, contentType.toString().indexOf(";"));
//        }
//        return contentType.toString();
//    }
//
//    private byte[] getNewBody(ServerWebExchange exchange, DataBuffer cachedRequestBody, Charset charset, String switchContentType) {
//        return switch (switchContentType) {
//            case MediaType.APPLICATION_JSON_VALUE,
//                    MediaType.TEXT_PLAIN_VALUE -> getJsonBody(exchange, cachedRequestBody, charset);
//            case MediaType.MULTIPART_FORM_DATA_VALUE -> getMultiPartFormBody(exchange, cachedRequestBody, charset);
//            case MediaType.APPLICATION_FORM_URLENCODED_VALUE -> getFormBody(exchange, cachedRequestBody, charset);
//            default -> new byte[0];
//        };
//    }
//
//    private byte[] getJsonBody(ServerWebExchange exchange, DataBuffer requestBody, @NonNull Charset charset) {
//        String raw = BodyUtils.toRaw(requestBody);
//        String newRaw = xssEncode(raw);
//        ServerHttpRequest request = exchange.getRequest();
//        HttpHeaders headers = request.getHeaders();
//        ProxyModel proxyModel = new ProxyModel().setPath(request.getURI().getPath())
//                .setMethod(HttpMethod.POST).setHeaders(headers);
//        if (StringUtils.isNotEmpty(newRaw)) {
//            proxyModel.setParams(JSONUtil.toBean(newRaw, Map.class));
//        }
//        return buildProxyParams(proxyModel).getBytes(charset);
//    }
//
//    private ServerHttpRequestDecorator decorate(ServerHttpRequest request, HttpHeaders headers, byte[] body) {
//        return new ServerHttpRequestDecorator(request) {
//
//            @Override
//            public HttpHeaders getHeaders() {
//                long contentLength = headers.getContentLength();
//                final HttpHeaders httpHeaders = new HttpHeaders();
//                httpHeaders.putAll(headers);
//                if (contentLength > 0) {
//                    httpHeaders.setContentLength(contentLength);
//                } else {
//                    httpHeaders.remove(HttpHeaders.CONTENT_LENGTH);
//                    httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
//                }
//                httpHeaders.set(HttpHeaders.CONTENT_TYPE.toLowerCase(), MediaType.APPLICATION_FORM_URLENCODED_VALUE);
//                httpHeaders.set(URI_HEADER, PROXY_URI);
//                return httpHeaders;
//            }
//
//            @Override
//            public Flux<DataBuffer> getBody() {
//                if (body == null || body.length == 0) {
//                    return Flux.empty();
//                } else {
//                    return DataBufferUtils.read(new ByteArrayResource(body),
//                            new NettyDataBufferFactory(ByteBufAllocator.DEFAULT),
//                            Math.toIntExact(body.length));
//                }
//            }
//
//            @Override
//            public URI getURI() {
//                return URI.create(PROXY_URI);
//            }
//        };
//    }
//
//
//    private String xssEncode(String s) {
//        if (StringUtils.isEmpty(s)) {
//            return Strings.EMPTY;
//        }
//        return stripXss(s);
//    }
//
//    private String stripXss(@NonNull String value) {
//        String cleanValue = NULL_CHAR.matcher(value).replaceAll("");
//        for (Pattern pattern : XSS_PATTERN) {
//            if (pattern.matcher(cleanValue).find()) {
//                return "";
//            }
//        }
//        return cleanValue;
//    }
//}
